package cc.abanlee.framework.security.core.filter;

import cc.abanlee.framework.common.exception.ServiceException;
import cc.abanlee.framework.security.core.LoginUser;
import cc.abanlee.framework.security.core.util.SecurityFrameworkUtils;
import cc.abanlee.framework.web.core.util.WebFrameworkUtils;
import cc.abanlee.module.system.api.oauth2.OAuth2TokenApi;
import cc.abanlee.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author: create by
 * @version: v1.0
 * @description:
 * @date:2022/8/30
 */
@RequiredArgsConstructor
public class TokenAuthenticationFilter extends OncePerRequestFilter {
//    @Autowired
//    private RedisTemplate redisTemplate;

    private final OAuth2TokenApi oauth2TokenApi;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String token = SecurityFrameworkUtils.obtainAuthorization(request,"Authorization");
        if (StrUtil.isNotEmpty(token)) {
            Integer userType = WebFrameworkUtils.getLoginUserType(request);

            try {

                LoginUser loginUser = buildLoginUserByToken(token, userType);

                // 2. 设置当前用户
                if (loginUser != null) {
                    SecurityFrameworkUtils.setLoginUser(loginUser, request);
                }

            }catch (Throwable ex){
//                CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
//                ServletUtils.writeJSON(response, result);
                return;
            }

        }


        // 继续过滤链
        filterChain.doFilter(request, response);
//        //获取token
//        String token = request.getHeader("token");
//        if (!StringUtils.hasText(token)) {
//            //放行
//            filterChain.doFilter(request, response);
//            return;
//        }
//
//        String userName;
//        try {
//            Claims claims = JwtUtil.parseJWT(token);
//            userName=claims.getSubject();
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException("token非法");
//        }
//
//        //从redis中获取用户信息
//        String redisKey = "token-" + userName;
//        Object o = redisTemplate.opsForValue().get(redisKey);
//        if(Objects.isNull(o)||!Objects.equals(o,token)){
//            throw new RuntimeException("用户未登录");
//        }
//
//        //存入SecurityContextHolder
//
//        // 角色集合
//        List<GrantedAuthority> authorities = new ArrayList<>();
//        // 角色必须以`ROLE_`开头，数据库中没有，则在这里加
//        authorities.add(new SimpleGrantedAuthority( "ROLE_user"));
//
//        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(userName,null,authorities);
//        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
//        //放行
//        filterChain.doFilter(request, response);

    }

    private LoginUser buildLoginUserByToken(String token, Integer userType) {
        try {
            OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token);
            if (accessToken == null) {
                return null;
            }
            // 用户类型不匹配，无权限
            if (ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
                throw new AccessDeniedException("错误的用户类型");
            }
            // 构建登录用户
            return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
                    .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes());
        } catch (ServiceException serviceException) {
            // 校验 Token 不通过时，考虑到一些接口是无需登录的，所以直接返回 null 即可
            return null;
        }
    }
}
